package com.mingtu.jgspatrol.view;

import static com.mingtu.jgspatrol.utils.MyConstant.MAX_ZOOM;

import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.location.DPoint;
import com.amap.api.maps.AMap;
import com.amap.api.maps.AMapOptions;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.LocationSource;
import com.amap.api.maps.MapView;
import com.amap.api.maps.MapsInitializer;
import com.amap.api.maps.UiSettings;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.api.maps.model.PolygonOptions;
import com.amap.api.maps.model.TileOverlay;
import com.amap.api.maps.model.TileOverlayOptions;
import com.blankj.utilcode.util.ActivityUtils;
import com.blankj.utilcode.util.StringUtils;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.hjq.gson.factory.GsonFactory;
import com.hjq.permissions.OnPermissionCallback;
import com.hjq.permissions.Permission;
import com.hjq.permissions.XXPermissions;
import com.lxj.xpopup.XPopup;
import com.lxj.xpopup.interfaces.OnConfirmListener;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.cache.CacheMode;
import com.lzy.okgo.model.Response;
import com.mingtu.common.base.BaseApplication;
import com.mingtu.common.bean.ResAreaBean;
import com.mingtu.common.utils.Constant;
import com.mingtu.common.utils.MyLogUtil;
import com.mingtu.common.utils.TileUtils;
import com.mingtu.jgspatrol.R;
import com.mingtu.jgspatrol.callback.MyStringDialogCallback;
import com.mingtu.jgspatrol.utils.MyConstant;

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName :
 * @Author : wkk
 * @Date : 2021-12-15 11:31:19
 * @Email : 1281573890@qq.com
 * @Eescription :
 */
public class CommonMapView extends FrameLayout implements LocationSource, AMapLocationListener, View.OnClickListener {

    private Context context;
    private AMap aMap;
    private MapView mapView;
    private TileOverlayOptions tileOverlayOptions;
    private TileOverlay tileOverlay;
    private View view;
    private LatLng location;
    private OnLocationChangedListener mListener;
    private AMapLocationClient locationClient = null;
    private AMapLocation myAMapLocation;
    private int locationNum = 0;

    public CommonMapView(Context context) {
        this(context, (AttributeSet) null, 0);
    }

    public CommonMapView(Context context, AttributeSet attributeSet) {
        this(context, attributeSet, 0);
    }

    public CommonMapView(Context context, AttributeSet attributeSet, int i) {
        super(context, attributeSet, i);
        view = LayoutInflater.from(context).inflate(R.layout.layout_common_map_view, this, true);
        ImageView imageView = view.findViewById(R.id.iv_location);
        imageView.setOnClickListener(this);
        this.context = context;
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        deactivate();
        //自定义瓦片
        if (tileOverlay != null) {
            tileOverlay.setVisible(false);
            tileOverlay.remove();
        }
        if (aMap != null) {
            mapView.onDestroy();
            aMap.clear();
        }

    }

    public AMap getAMap() {
        return aMap;
    }

    public void amapMoveCamera() {
        if (aMap != null) {
            aMap.animateCamera(CameraUpdateFactory.changeLatLng(location));
            aMap.moveCamera(CameraUpdateFactory.zoomTo(Constant.MAP_ZOOM));
            mListener.onLocationChanged(myAMapLocation);// 显示系统小蓝点
        }
    }

    public TileOverlay getTileOverlay() {
        return tileOverlay;
    }

    public void setMapParam(Bundle savedInstanceState) {
        //同意隐私状态,需要在初始化地图之前完成
        MapsInitializer.updatePrivacyShow(context, true, true);
        MapsInitializer.updatePrivacyAgree(context, true);
        mapView = view.findViewById(R.id.mapView);
        mapView.onCreate(savedInstanceState);
        aMap = mapView.getMap();
        aMap.setLocationSource(this);// 设置定位监听
        //地图模式可选类型：MAP_TYPE_NORMAL,MAP_TYPE_SATELLITE,MAP_TYPE_NIGHT
        aMap.setMapType(AMap.MAP_TYPE_SATELLITE);// 矢量地图模式
        UiSettings uiSettings = aMap.getUiSettings();
        uiSettings.setMyLocationButtonEnabled(false);// 设置默认定位按钮是否显示
        uiSettings.setZoomControlsEnabled(false);
        uiSettings.setScaleControlsEnabled(true);
        uiSettings.setLogoPosition(AMapOptions.LOGO_POSITION_BOTTOM_RIGHT);

        aMap.setMaxZoomLevel(MAX_ZOOM);
        aMap.setMapTextZIndex(1);
        aMap.moveCamera(CameraUpdateFactory.zoomTo(Constant.MAP_ZOOM_TWO));
        MyLocationStyle myLocationStyle = new MyLocationStyle();
        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER);//连续定位、蓝点不会移动到地图中心点，定位点依照设备方向旋转，并且蓝点会跟随设备移动。
        // 自定义定位蓝点图标
        myLocationStyle.myLocationIcon(
                BitmapDescriptorFactory.fromResource(R.mipmap.gps_point));
        // 自定义精度范围的圆形边框颜色
        myLocationStyle.strokeColor(Color.argb(100, 47, 185, 97));
        // 自定义精度范围的圆形边框宽度
        myLocationStyle.strokeWidth(0.1F);
        // 设置圆形的填充颜色
        myLocationStyle.radiusFillColor(Color.argb(100, 47, 185, 97));
        // 将自定义的 myLocationStyle 对象添加到地图上
        aMap.setMyLocationStyle(myLocationStyle);
        aMap.setMyLocationEnabled(true);// 设置为true表示显示定位层并可触发定位，false表示隐藏定位层并不可触发定位，默认是false
//        String longitude = SPStaticUtils.getString(SPTools.lng);
//        String latitude = SPStaticUtils.getString(SPTools.lat);
//        if (!StringUtils.isEmpty(longitude) && !StringUtils.isEmpty(latitude)) {
//            location = new LatLng(Double.parseDouble(latitude), Double.parseDouble(longitude));
//            //添加Marker
//            MarkerOptions markerOptions = new MarkerOptions()
//                    .position(location)
//                    .icon(BitmapDescriptorFactory.fromResource(R.mipmap.sb_icon_wz))
//                    .infoWindowEnable(false);
//            aMap.addMarker(markerOptions);
//            aMap.moveCamera(CameraUpdateFactory.changeLatLng(location));
//        }


        //自定义瓦片
        tileOverlayOptions = TileUtils.getTileOverlayOptions();
        tileOverlay = aMap.addTileOverlay(tileOverlayOptions);
        getAreaData();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.iv_location:
                if (!XXPermissions.isGranted(context, Permission.ACCESS_COARSE_LOCATION) ||
                        !XXPermissions.isGranted(context, Permission.ACCESS_FINE_LOCATION)) {
                    new XPopup.Builder(ActivityUtils.getTopActivity())
                            .isDestroyOnDismiss(true)
                            .dismissOnTouchOutside(true)
                            .hasShadowBg(true)
                            .asConfirm(context.getResources().getString(R.string.text_tip), context.getResources().getString(R.string.text_location_auth),
                                    context.getResources().getString(R.string.text_cancle), context.getResources().getString(R.string.text_sure),

                                    new OnConfirmListener() {
                                        @Override
                                        public void onConfirm() {
                                            locationPermissions();
                                        }
                                    }, null, false)
                            .show();
                    return;
                } else {
                    amapMoveCamera();
                }

                break;
        }
    }

    public void locationPermissions() {
        //为了适配android11，这个权限单独申请。如果申请的权限中包含后台定位权限， 那么这里面则不能包含和定位无关的权限，否则框架会抛出异常，
        // 因为 ACCESS_BACKGROUND_LOCATION 和其他非定位权限定位掺和在一起申请，在 Android 11 上会出现不申请直接被拒绝的情况。
        //也就是说，如果你想获得后台定位权限，必须弹窗两次：
        //第一次，申请普通定位权限的弹窗。
        //第二次，在用户同意了普通定位权限之后，申请 后台定位权限时弹窗。
        //这里也要千万注意，在没有拿到 普通定位权限的时候，直接申请后台定位权限，将不弹窗直接授权失败。
        XXPermissions.with(context)
                .permission(Permission.ACCESS_COARSE_LOCATION)
                .permission(Permission.ACCESS_FINE_LOCATION)
                .request(new OnPermissionCallback() {
                    @Override
                    public void onGranted(List<String> permissions, boolean all) {
                        if (permissions.contains(Permission.ACCESS_COARSE_LOCATION) ||
                                permissions.contains(Permission.ACCESS_FINE_LOCATION)) {

                            backgroundPermissions();

                            if (myAMapLocation != null && mListener != null) { //防止点击定位按钮的时候不出现小蓝点
                                mListener.onLocationChanged(myAMapLocation);// 显示系统小蓝点
                                aMap.moveCamera(CameraUpdateFactory.changeLatLng(location));
                            } else {
                                aMap.moveCamera(CameraUpdateFactory.changeLatLng(location));
                            }
                        }
                    }

                    @Override
                    public void onDenied(List<String> permissions, boolean never) {
                        if (never) {
                            // 如果是被永久拒绝就跳转到应用权限系统设置页面
                            new XPopup.Builder(ActivityUtils.getTopActivity())
                                    .isDestroyOnDismiss(true)
                                    .dismissOnTouchOutside(true)
                                    .hasShadowBg(true)
                                    .asConfirm(context.getResources().getString(R.string.text_tip), context.getResources().getString(R.string.text_location_auth),
                                            context.getResources().getString(R.string.text_cancle), context.getResources().getString(R.string.text_sure),

                                            new OnConfirmListener() {
                                                @Override
                                                public void onConfirm() {
                                                    XXPermissions.startPermissionActivity(ActivityUtils.getTopActivity(), permissions);
                                                }
                                            }, null, false)
                                    .show();
                        } else {

                        }

                    }
                });
    }

    private void backgroundPermissions() {
        XXPermissions.with(context)
                .permission(Permission.ACCESS_BACKGROUND_LOCATION)
                .request(new OnPermissionCallback() {
                    @Override
                    public void onGranted(List<String> permissions, boolean all) {

                    }

                    @Override
                    public void onDenied(List<String> permissions, boolean never) {
                    }
                });
    }

    @Override
    public void onLocationChanged(AMapLocation aMapLocation) {
        if (mListener != null && aMapLocation != null) {
            if (aMapLocation != null && aMapLocation.getErrorCode() == 0) {
                locationNum++;
                double longitude = aMapLocation.getLongitude();
                double latitude = aMapLocation.getLatitude();
                location = new LatLng(latitude, longitude);
                //定位的时候用
                myAMapLocation = aMapLocation;
                if (locationNum == 1) {
                    //第一次定位将地图移动到蓝点
                    aMap.moveCamera(CameraUpdateFactory.changeLatLng(location));
                    mListener.onLocationChanged(aMapLocation);// 显示系统小蓝点
                }
            } else {
                StringBuffer sb1 = new StringBuffer();
                sb1.append("定位失败" + "\n");
                sb1.append("错误码:" + aMapLocation.getErrorCode() + "\n");
                sb1.append("错误信息:" + aMapLocation.getErrorInfo() + "\n");
                sb1.append("错误描述:" + aMapLocation.getLocationDetail() + "\n");
                MyLogUtil.e("loaction", sb1.toString());
            }
        }
    }

    @Override
    public void activate(OnLocationChangedListener listener) {
        mListener = listener;
        if (locationClient == null) {
            try {
                AMapLocationClient.updatePrivacyShow(context, true, true);
                AMapLocationClient.updatePrivacyAgree(context, true);
                locationClient = new AMapLocationClient(BaseApplication.getContext());
                AMapLocationClientOption option = new AMapLocationClientOption();
                //设置定位监听
                //设置为高精度定位模式
                option.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
                //设获取高精度模式下单次定位是否优先返回卫星定位信息,只有在单次定位高精度定位模式下有效
                //为true时，会等待卫星定位结果返回，最多等待30秒，若30秒后仍无卫星定位结果返回，返回网络定位结果
                option.setGpsFirst(true);
                option.setGpsFirstTimeout(5 * 1000);
                //option.setLocationMode(AMapLocationClientOption.AMapLocationMode.Device_Sensors);
                //定位场景
                option.setLocationPurpose(AMapLocationClientOption.AMapLocationPurpose.Sport);
                //设置setOnceLocationLatest(boolean b)接口为true，启动定位时SDK会返回最近3s内精度最高的一次定位结果。如果设置其为true，setOnceLocation(boolean b)接口也会被设置为true，反之不会，默认为false。
                option.setInterval(Constant.LOCATION_INTERVAL_TIME);
                //自3.1.0版本开始，不限定定位类型，当定位类型不是AMapLocation.LOCATION_TYPE_GPS时，可以通过 AMapLocationClientOption.setSensorEnable(boolean) 控制是否返回速度值，当设置为true时会通过手机传感器获取速度,如果手机没有对应的传感器会返回0.0
                option.setSensorEnable(true);
                //设置定位参数
                locationClient.setLocationOption(option);
                locationClient.disableBackgroundLocation(true);
//                locationClient.enableBackgroundLocation(NotificationUtils.NOTIFY_ID, NotificationUtils.buildNotification(BaseApplication.getContext()));
                // 此方法为每隔固定时间会发起一次定位请求，为了减少电量消耗或网络流量消耗，
                // 注意设置合适的定位时间的间隔（最小间隔支持为2000ms），并且在合适时间调用stopLocation()方法来取消定位请求
                // 在定位结束后，在合适的生命周期调用onDestroy()方法
                // 在单次定位情况下，定位无论成功与否，都无需调用stopLocation()方法移除请求，定位sdk内部会移除
                locationClient.startLocation();
                locationClient.setLocationListener(this);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void deactivate() {
        mListener = null;
        if (locationClient != null) {
            locationClient.stopLocation();
        }
    }

    /**
     * 巡护区域
     */
    private void getAreaData() {
        OkGo.<String>get(MyConstant.GET_AREA)
                .tag(this)
                .cacheMode(CacheMode.REQUEST_FAILED_READ_CACHE)
                .execute(new MyStringDialogCallback(ActivityUtils.getTopActivity()) {
                    @Override
                    public void onSuccess(Response<String> response) {
                        getAreaDataCommon(response);
                    }

                    @Override
                    public void onCacheSuccess(Response<String> response) {
                        super.onCacheSuccess(response);
                        getAreaDataCommon(response);
                    }

                    @Override
                    public void onError(Response<String> response) {
                        String result = response.body();
                        MyLogUtil.e(getClass().getSimpleName(), "onError==" + result);

                    }
                });
    }

    private void getAreaDataCommon(Response<String> response) {
        String result = response.body();
        if (!StringUtils.isEmpty(result)) {
            ResAreaBean resAreaBean = null;
            try {
                Gson gson = GsonFactory.getSingletonGson();
                resAreaBean = new ResAreaBean();
                resAreaBean = gson.fromJson(result, ResAreaBean.class);

                List<ResAreaBean.FeaturesBean> featuresBeans = resAreaBean.getFeatures();
                for (int i = 0; i < featuresBeans.size(); i++) {
                    ResAreaBean.FeaturesBean featuresBean = featuresBeans.get(i);
                    ResAreaBean.FeaturesBean.PropertiesBeanX propertiesBeanX = featuresBean.getProperties();
                    ResAreaBean.FeaturesBean.GeometryBean geometryBean = featuresBean.getGeometry();

                    String type = geometryBean.getType();
                    List<List<Double>> myList = null;
                    if (type.equals("MultiPolygon")) {
                        List<List<List<List<Double>>>> coordinates = (List<List<List<List<Double>>>>) geometryBean.getCoordinates();
                        myList = coordinates.get(0).get(0);

                    } else if (type.equals("Polygon")) {
                        List<List<List<Double>>> coordinates = (List<List<List<Double>>>) geometryBean.getCoordinates();
                        myList = coordinates.get(0);
                    }
                    List<DPoint> points = new ArrayList<DPoint>();  //存放地里围栏需要的数据
                    List<LatLng> latLngs = new ArrayList<>();//存放单条区域的数据
                    for (int j = 0; j < myList.size(); j++) {
                        List<Double> latLngList = myList.get(j);
                        double gpsLat = latLngList.get(1);
                        double gpsLng = latLngList.get(0);
                        //gps 转高德的经纬度
//                                        double[] latlngs = GPSTransToAMap.transform(gpsLat, gpsLng);
//                                        LatLng latLng = new LatLng(latlngs[0], latlngs[1]);
//                                        points.add(new DPoint(latlngs[0], latlngs[1]));

                        LatLng latLng = new LatLng(gpsLat, gpsLng);
                        latLngs.add(latLng); //将坐标装到数组里
                        points.add(new DPoint(gpsLat, gpsLng));
                    }

                    PolygonOptions polygonOptions = new PolygonOptions();
                    polygonOptions.addAll(latLngs);
                    polygonOptions.strokeWidth(3);
                    polygonOptions.zIndex(45);
                    String gnfy = propertiesBeanX.getGnfq();

                    switch (gnfy) {
                        case "实验区":
                            polygonOptions.fillColor(context.getResources().getColor(R.color.bg_color_00f2));
                            polygonOptions.strokeColor(context.getResources().getColor(R.color.bg_color_00f));
                            aMap.addPolygon(polygonOptions);

                            break;
                        case "缓冲区":
                            polygonOptions.fillColor(context.getResources().getColor(R.color.bg_color_fff2));
                            polygonOptions.strokeColor(context.getResources().getColor(R.color.bg_color_fff));
                            aMap.addPolygon(polygonOptions);

                            break;
                        case "核心区":
                            polygonOptions.fillColor(context.getResources().getColor(R.color.bg_color_ff02));
                            polygonOptions.strokeColor(context.getResources().getColor(R.color.bg_color_ff0));
                            aMap.addPolygon(polygonOptions);

                            break;
                    }

                }

            } catch (JsonSyntaxException e) {
                e.printStackTrace();
            }

        }
    }
}
